package com.bree.erp.jsf.view;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.LazyDataModel;

import com.bree.erp.entity.MovementType;
import com.bree.erp.entity.PartUnit;
import com.bree.erp.entity.Project;
import com.bree.erp.entity.PurchaseRequisition;
import com.bree.erp.entity.Returns;
import com.bree.erp.entity.ReturnsBalance;
import com.bree.erp.entity.Warehouse;
import com.bree.erp.jsf.datatable.LazyBreeDataModel;
import com.bree.erp.jsf.httpsess.Clipboard;
import com.bree.erp.jsf.httpsess.SessionDataKey;
import com.bree.erp.jsf.httpsess.UserSessionData;
import com.bree.erp.service.PartUnitService;
import com.bree.erp.service.PurchaseRequisitionService;
import com.bree.erp.service.ReturnsBalanceService;
import com.bree.erp.service.ReturnsService;
import com.bree.erp.service.WarehouseService;

@ManagedBean(name="dtPartUnitLazyView")
@ViewScoped
public class PartUnitLazyView {
	
	private static Logger LOG = Logger.getLogger(PartUnitLazyView.class);
    
    @EJB
    private PartUnitService puService;
    
    @EJB
    private ReturnsBalanceService balanceService;
    
    @EJB
    private ReturnsService returnsService;
    
    @EJB
    private PurchaseRequisitionService prService;
    
    @EJB
    private WarehouseService warehouseService;

	@ManagedProperty(value="#{dtItemRequestLazyView}")
    private ItemRequestLazyView itemRequestLazyView;

	@ManagedProperty(value="#{userSession}")
	private UserSessionData userSession;
	
	@ManagedProperty(value="#{clipboardSession}")
	private Clipboard clipboard;

    private LazyDataModel<PartUnit> lazyModel;
    
    private PartUnit selectedItem;
    private List<Returns> warehouseSelection;
    
    private double quantity;
	private double qtyReserveOrder;
	private double maxQtyReserve;
	private String warehouseReserve;
    
    @PostConstruct
    public void init() {
    	lazyModel = new LazyBreeDataModel<PartUnit, PartUnitService, Long>(puService, 0L);
    }
    
   public void onRowSelect(SelectEvent event) {
	   
	   PartUnit partUnit = (PartUnit) event.getObject();
       FacesMessage msg = new FacesMessage("Item Selected", partUnit.getId() + "");
       FacesContext.getCurrentInstance().addMessage(null, msg);
       
       Long partUnitId = partUnit.getId();
       warehouseSelection = returnsService.listPerPartUnit(partUnitId);
       if(warehouseSelection.size() > 0) {
    	   Returns returns = warehouseSelection.get(0);
    	   warehouseReserve = returns.getWarehouse().getId();
    	   qtyReserveOrder = maxQtyReserve = returns.getQuantity() - clipboard.getWareshouseReserved(warehouseReserve, partUnitId);
       } else {
    	   maxQtyReserve = 0;
       }
   }
   
   public void addItem() {
	   
	   
	   LOG.debug("PartUnit: " + (this.selectedItem == null ? "<null>" : this.selectedItem.getShortName()) + "; quantity: " + quantity);
	   
	   if(quantity <= 0.0) {
		   LOG.debug("no-op for zero or negative quantity");
		   return;
	   }
	
	   itemRequestLazyView.addItem(selectedItem, quantity);
   }
   
   public Map<Long, Double> getMapBalance() {
	   
	   Map<Long, Double> mapBalance = new HashMap<Long, Double>();
	
	   // TODO: optimization point here!
	   List<ReturnsBalance> list = balanceService.sumPartUnits();
	   for(ReturnsBalance item : list) {
		   mapBalance.put(item.getPartUnit().getId(), item.getTotalBalance());
	   }
	   
	   return mapBalance;
   }
   
   public void warehouseHasChanged(AjaxBehaviorEvent vce){  
	   String warehouseId= (String) ((UIOutput) vce.getSource()).getValue();
	   maxQtyReserve = 0;
	   for(Returns returns : warehouseSelection) {
		   if(returns.getWarehouse().getId().equals(warehouseId)) {
			   qtyReserveOrder = maxQtyReserve = returns.getQuantity();
		   }
	   }
   }
   
   public void reserve() {
	   
	   LOG.debug("reserve: " + selectedItem + "; quantity: " + qtyReserveOrder);
	   
	   Long prId = userSession.get(SessionDataKey.SELECTED_PURCHASE_REQUISITION_ID, Long.class);
	   PurchaseRequisition pr = prService.read(prId);
	   
	   if(StringUtils.isEmpty(warehouseReserve)) {
		   LOG.debug("no-op on empty warehouse");
		   return;
	   }
	   
	   Warehouse source = warehouseService.read(warehouseReserve);
	   
	   Returns reserve = new Returns();
	   
	   reserve.setWarehouse(source);
	   reserve.setMovementType(MovementType.RESERVE);
	   reserve.setPartUnit(selectedItem);
	   Project project = pr.getProject();
	   reserve.setProject(project);
	   reserve.setQuantity(qtyReserveOrder);
	   
	   clipboard.reserve(reserve);
   }
   

	/**
	 * @return the lazyModel
	 */
	public LazyDataModel<PartUnit> getLazyModel() {
		return lazyModel;
	}

	/**
	 * @param lazyModel the lazyModel to set
	 */
	public void setLazyModel(LazyDataModel<PartUnit> lazyModel) {
		this.lazyModel = lazyModel;
	}

	/**
	 * @return the selectedItem
	 */
	public PartUnit getSelectedItem() {
		return selectedItem;
	}

	/**
	 * @param selectedItem the selectedItem to set
	 */
	public void setSelectedItem(PartUnit selectedItem) {
		this.selectedItem = selectedItem;
	}

	/**
	 * @return the quantity
	 */
	public double getQuantity() {
		return quantity;
	}

	/**
	 * @param quantity the quantity to set
	 */
	public void setQuantity(double quantity) {
		this.quantity = quantity;
	}

	/**
	 * @return the itemRequestLazyView
	 */
	public ItemRequestLazyView getItemRequestLazyView() {
		return itemRequestLazyView;
	}

	/**
	 * @param itemRequestLazyView the itemRequestLazyView to set
	 */
	public void setItemRequestLazyView(ItemRequestLazyView itemRequestLazyView) {
		this.itemRequestLazyView = itemRequestLazyView;
	}

	/**
	 * @return the qtyReserveOrder
	 */
	public double getQtyReserveOrder() {
		return qtyReserveOrder;
	}

	/**
	 * @param qtyReserveOrder the qtyReserveOrder to set
	 */
	public void setQtyReserveOrder(double qtyReserveOrder) {
		this.qtyReserveOrder = qtyReserveOrder;
	}

	/**
	 * @return the maxQtyReserve
	 */
	public double getMaxQtyReserve() {
		return maxQtyReserve;
	}

	/**
	 * @param maxQtyReserve the maxQtyReserve to set
	 */
	public void setMaxQtyReserve(double maxQtyReserve) {
		this.maxQtyReserve = maxQtyReserve;
	}

	/**
	 * @return the warehouseReserve
	 */
	public String getWarehouseReserve() {
		return warehouseReserve;
	}

	/**
	 * @param warehouseReserve the warehouseReserve to set
	 */
	public void setWarehouseReserve(String warehouseReserve) {
		this.warehouseReserve = warehouseReserve;
	}

	/**
	 * @return the warehouseSelection
	 */
	public List<Returns> getWarehouseSelection() {
		return warehouseSelection;
	}

	/**
	 * @return the clipboard
	 */
	public Clipboard getClipboard() {
		return clipboard;
	}

	/**
	 * @param clipboard the clipboard to set
	 */
	public void setClipboard(Clipboard clipboard) {
		this.clipboard = clipboard;
	}

	/**
	 * @return the userSession
	 */
	public UserSessionData getUserSession() {
		return userSession;
	}

	/**
	 * @param userSession the userSession to set
	 */
	public void setUserSession(UserSessionData userSession) {
		this.userSession = userSession;
	}
}
